import React, { Component } from 'react';
import HelloComponent from './HelloComponent';

class App extends Component {

  //1.构造方法：在挂载之前,创建类实例获取React元素时被调用
  constructor(props) {
    super(props);
    console.log("App - constructor");
    this.state = {
      message: '你好啊，李银河',
      showComponent: true
    }
  }

  //3.装载过程：渲染完成, 组件第一次被挂载到DOM树上时被调用
  componentDidMount() {
    console.log("App - componentDidMount");
  }

  //4.更新过程：组件状态发生变化, 重新渲染后生成新的DOM树时被调用
  componentDidUpdate(prevProps, prevState) {
    console.log("App - componentDidUpdate");
  }

  changeText() {
    this.setState({
      message: 'Hello World',
    })
  }

  //5.隐藏组件，触发子组件的componentWillUnmount
  switchComponent() {
    this.setState({
      showComponent: !this.state.showComponent,
    })
  }

  //2.渲染组件：执行render函数, 渲染组件(在第一次加载和更新时被调用)
  render() { 
    console.log("App - render");
    const { message, showComponent } = this.state
    return ( 
      <div>
        <h2>{message}</h2>
        <button onClick={() => this.changeText()}>点击修改</button>
        {showComponent && <HelloComponent/>}
        <button onClick={() => this.switchComponent()}>切换</button>
      </div> 
    );
  }
}

/*

使用React.createElement或JSX编写React组件（实际上所有的JSX代码最后都会转换成React.createElement(...)）

ReactDOM.render将生成好的虚拟DOM渲染到指定容器上，其中采用了批处理、事务等机制并且对特定浏览器进行了性能优化，最终转换为真实DOM。

render函数内部实际调用了_renderSubtreeIntoContainer，在_renderNewRootComponent中调用instantiateReactComponent对我们传入的组件进行分类包装：

根据组件的类型，React根据原组件创建了下面四大类组件，对组件进行分类渲染：
  ReactDOMEmptyComponent:空组件
  ReactDOMTextComponent:文本
  ReactDOMComponent:原生DOM
  ReactCompositeComponent:自定义React组件

他们都具备以下三个方法：

  construct:用来接收ReactElement进行初始化。
  mountComponent:用来生成ReactElement对应的真实DOM或DOMLazyTree。
  unmountComponent:卸载DOM节点，解绑事件。

*/
 
export default App;